package routefinder.algorithm;

import routefinder.*;
import routefinder.exception.RouteFinderException;
import java.util.logging.Logger;

/**
 * Implements a simple breadth first search on the graph.
 * 
 * @author luky
 */
public class MyBFS {

    /**
     * The graph.
     */
    private final IRoutesMap map;
    /**
     * Accumulates the amount of possible trips from the starting city to the destination.
     */
    private int trips;
    /**
     * keeps track of the destination node, so we know when something funny happened.
     */
    private City destinationNode;
    /**
     * keeps track of the source node, so we know when something funny happened.
     */
    private City sourceNode;
    /**
     * The maximum distance of a route
     */
    private int maximumDistance;

    public MyBFS(IRoutesMap map) {
        if (map == null) {
            throw new RouteFinderException("A map must be supplied");
        }
        this.map = map;
    }

    /**
     * Initialize all data structures used by the algorithm.
     *
     * @param start the source node
     */
    private void init(City start, City destination, int maximumDistance) {
        this.maximumDistance = maximumDistance;
        sourceNode = start;
        destinationNode = destination;
        trips = 0;
    }

    public int execute(City start, City destination, int maximumDistance) {
        Logger.getLogger(Dijkstra.class.getName()).info("Executing Dijkstra on: " + start + " " + destination);
        init(start, destination, maximumDistance);
        bfs10("", 0, null);
        return trips;
    }

    private void bfs10(String routePath, int cost, City previousNode) {
        if (cost >= maximumDistance) {
            return;
        }

        if (cost > 0 && routePath.endsWith(destinationNode.getName())) { //TODO use Route
            Logger.getLogger(MyBFS.class.getName()).info(routePath + ", " + cost);
            trips++;
        }

        if (previousNode == null) {
            previousNode = sourceNode;
        }

        // visit neighbors
        for (Link v : map.getDestinations(previousNode)) {
            int newCost = v.getDistance();
            if (newCost > 0) {
                bfs10(routePath + v.getCity().getName(), cost + newCost, v.getCity());
            }
        }
    }
}
